// ============================================
// cmd/server/main.go
// ============================================

package main

import (
	"context"
	"flag"
	"fmt"
	"os"
	"os/signal"
	"syscall"
	"time"

	"github.com/sirupsen/logrus"

	"virt-manager-go/internal/api"
	"virt-manager-go/internal/config"
	"virt-manager-go/internal/console"
	"virt-manager-go/internal/domain"
	"virt-manager-go/internal/service"

	// Swagger documentation
	_ "virt-manager-go/docs"

	swaggerFiles "github.com/swaggo/files"
	ginSwagger "github.com/swaggo/gin-swagger"
	"libvirt.org/go/libvirt"
)

//	@title			Virt-Manager-Go API
//	@version		1.0
//	@description	A libvirt management API service written in Go
//	@termsOfService	http://swagger.io/terms/

//	@contact.name	API Support
//	@contact.url	http://www.swagger.io/support
//	@contact.email	support@swagger.io

//	@license.name	Apache 2.0
//	@license.url	http://www.apache.org/licenses/LICENSE-2.0.html

//	@host		localhost:8080
//	@BasePath	/api/v1

//	@securityDefinitions.basic	BasicAuth

//	@externalDocs.description	OpenAPI
//	@externalDocs.url			https://swagger.io/resources/open-api/

var (
	configFile = flag.String("config", "config.yaml", "Configuration file path")
	host       = flag.String("host", "0.0.0.0", "Server host")
	port       = flag.Int("port", 8080, "Server port")
	logLevel   = flag.String("log-level", "info", "Log level (debug, info, warn, error)")
)

func main() {
	flag.Parse()

	// 初始化事件处理
	if err := libvirt.EventRegisterDefaultImpl(); err != nil {
		fmt.Fprintf(os.Stderr, "Failed to register event implementation: %v\n", err)
		os.Exit(1)
	}

	// 初始化日志
	logger := setupLogger(*logLevel)
	logger.Info("Starting virt-manager-go server")

	// 加载配置（可选）
	cfg, err := config.Load(*configFile)
	if err != nil {
		logger.WithError(err).Warn("Failed to load config, using defaults")
		cfg = config.Default()
	}

	// 初始化所有服务
	connMgr := service.NewConnectionService(logger)
	vmService := service.NewVMService(connMgr, logger)
	storageService := service.NewStoragePoolService(connMgr, logger)
	networkService := service.NewNetworkService(connMgr, logger)
	snapshotService := service.NewSnapshotService(connMgr, vmService, logger)
	migrationService := service.NewMigrationService(connMgr, logger)
	batchService := service.NewBatchService(vmService, snapshotService, logger)
	eventService := service.NewEventService(connMgr, logger)

	// 初始化控制台代理
	serialProxy := console.NewSerialProxy(connMgr, logger)
	graphicsProxy := console.NewGraphicsProxy(connMgr, logger)

	// 自动连接本地 libvirt
	ctx := context.Background()
	// 自动连接本地 libvirt（可选）
	if cfg.Libvirt.AutoConnect {
		ctx := context.Background()
		connID, err := connMgr.Connect(ctx, cfg.Libvirt.DefaultURI, &domain.ConnectionOptions{})
		if err != nil {
			logger.WithError(err).Error("Failed to auto-connect to libvirt")
		} else {
			logger.WithFields(logrus.Fields{
				"connection_id": connID,
				"uri":           cfg.Libvirt.DefaultURI,
			}).Info("Auto-connected to libvirt")
			// 启动事件监听
			if err := eventService.StartListening(ctx, connID); err != nil {
				logger.WithError(err).Warn("Failed to start event listening")
			}
		}
	}

	router := api.NewRouter(
		vmService,
		storageService,
		networkService,
		snapshotService,
		migrationService,
		batchService,
		eventService,
		serialProxy,
		graphicsProxy,
		connMgr,
		logger,
	)

	// 注册Swagger路由
	router.Engine().GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))

	// 启动服务器
	addr := fmt.Sprintf("%s:%d", *host, *port)

	// 优雅关闭
	go func() {
		if err := router.Run(addr); err != nil {
			logger.WithError(err).Fatal("Failed to start server")
		}
	}()

	logger.WithField("address", addr).Info("Server started successfully")
	logger.Info("API documentation: http://" + addr + "/swagger/index.html")
	logger.Info("Health check: http://" + addr + "/health")

	// 启动事件循环协程
	go func() {
		for {
			if err := libvirt.EventRunDefaultImpl(); err != nil {
				logger.WithError(err).Error("Failed to run event loop")
				time.Sleep(1 * time.Second)
			}
		}
	}()

	// 等待中断信号
	quit := make(chan os.Signal, 1)
	signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
	<-quit

	logger.Info("Shutting down server...")

	// 清理资源
	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()

	// 断开所有连接
	connections, _ := connMgr.ListConnections(ctx)
	for _, conn := range connections {
		if err := connMgr.Disconnect(ctx, conn.ID); err != nil {
			logger.WithError(err).Warnf("Failed to disconnect %s", conn.ID)
		}
	}

	logger.Info("Server stopped gracefully")
}

func setupLogger(level string) *logrus.Logger {
	logger := logrus.New()
	logger.SetFormatter(&logrus.JSONFormatter{
		TimestampFormat: time.RFC3339,
	})

	logLevel, err := logrus.ParseLevel(level)
	if err != nil {
		logLevel = logrus.InfoLevel
	}
	logger.SetLevel(logLevel)

	return logger
}
